package com.cs307.redcross.client;

import java.io.Serializable;
import java.util.Vector;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.CheckBox;

public class GroupsContent extends Content implements Serializable {
	private static final long serialVersionUID = -1189011235559691201L;
	private DatabaseHandlerServiceAsync databaseHandlerService = (DatabaseHandlerServiceAsync) GWT.create(DatabaseHandlerService.class);
	private final String relogString = "If this problem persists try relogging into the system.";
	
	Vector<Group> groupVector = new Vector<Group>();
	
	// the following are used when editing events
	Vector<Person> personVector = new Vector<Person>();
	Vector<Person> addedPersonVector = new Vector<Person>();
	
	Group cancelGroup;
	Group selectedGroup;
	Person selectedPerson;
	
	Group groupCopy;
	Boolean callbackReceived;
	
	// UI Widgets
	ListBox groupListbox;
	TextBox groupNameTextbox;
	Button addGroupButton;
	Button deleteGroupButton;
	Button editGroupButton;
	Button saveGroupButton;
	Button cancelButton;
	PopupPanel popup;
	AddPersonPopupPanel appp;
	LoadingPopupPanel lpp = new LoadingPopupPanel();
	TextArea descriptionTextArea;
	Label lblAdditionalPeople;
	ListBox personListBox;
	Button addPersonButton;
	Button removePersonButton;
	CheckBox privateCheckbox;
	
	public GroupsContent() {	
		lpp.setAutoHideEnabled(false);
		lpp.setModal(true);

		ContentPanel.getInstance().showLoading(1, 80, 350);
		databaseHandlerService.getAllGroups(new AsyncCallback<Vector<Group>>() {
			
			@Override
			public void onSuccess(Vector<Group> result) {
				if (result != null && !result.isEmpty()) {
					for (Group group : result) {
						if (group == null)
							continue;
						
						groupVector.add(group);
						groupListbox.addItem(group.getName());
					}
				}
				ContentPanel.getInstance().hideLoadingPopup(1);
			}
			
			@Override
			public void onFailure(Throwable caught) {
				ContentPanel.getInstance().hideLoadingPopup(1);
				Window.alert("Error: Failed to contact server. " + relogString);
				return;
			}
		});
		
		AbsolutePanel absolutePanel = new AbsolutePanel();
		initWidget(absolutePanel);
		absolutePanel.setSize("879px", "647px");
		
		Label lblSelectEvent = new Label("Groups:");
		absolutePanel.add(lblSelectEvent, 10, 10);
		
		Label lblEventName = new Label("Group Name:");
		absolutePanel.add(lblEventName, 307, 10);
		lblEventName.setSize("79px", "18px");
		
		groupNameTextbox = new TextBox();
		absolutePanel.add(groupNameTextbox, 307, 34);
		groupNameTextbox.setSize("331px", "13px");
		
		addGroupButton = new Button("Add");
		addGroupButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				addedPersonVector = new Vector<Person>();
				personVector = new Vector<Person>();
				clearForm();
				
				groupListbox.setSelectedIndex(-1);
				selectedGroup = null;
							
				databaseHandlerService.getAllPeople(new AsyncCallback<Vector<Person>>() {
					
					@Override
					public void onSuccess(Vector<Person> result) {
						if (result != null && !result.isEmpty()) {
							for (Person person : result) {
								if (person == null)
									continue;
								
								if (person.getUsername().equals("dev"))
									continue;
								
								personVector.add(person);
							}
						}
					}
					
					@Override
					public void onFailure(Throwable caught) {
						Window.alert("Error: Failed to contact server. " + relogString);
					}
				});
				
				groupNameTextbox.setText("New Group");
				
				enableForm();
				groupListbox.setEnabled(false);
			}
		});
		absolutePanel.add(addGroupButton, 10, 604);
		
		deleteGroupButton = new Button("Delete");
		deleteGroupButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if (selectedGroup != null && groupListbox.getSelectedIndex() != -1) {
					popup = new PopupPanel();
					popup.setPopupPosition(400, 400);
					VerticalPanel vp = new VerticalPanel();
					vp.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
					vp.add(new Label("Are you sure you want to delete " + selectedGroup.getName() + "? You cannot undo this action."));
					
					Button yesButton = new Button("Yes");
					yesButton.addClickHandler(new ClickHandler() {
						
						@Override
						public void onClick(ClickEvent event) {
							popup.hide();
							popup.clear();
							databaseHandlerService.delete(selectedGroup, new AsyncCallback<Boolean>() {
								
								@Override
								public void onSuccess(Boolean result) {
									if (result) {
										groupVector.remove(groupListbox.getSelectedIndex());
										groupListbox.removeItem(groupListbox.getSelectedIndex());
										selectedGroup = null;
										clearForm();
										disableForm();
										Window.alert("Group successfully deleted. ");
									}
									else {
										Window.alert("An error ocurred while trying to delete the Event. Please try again. " + relogString);
									}
								}
								
								@Override
								public void onFailure(Throwable caught) {
									Window.alert("An error ocurred while trying to delete the Event. Please try again. " + relogString);
								}
							});
						}
					});
					
					Button noButton = new Button("No");
					noButton.addClickHandler(new ClickHandler() {
						
						@Override
						public void onClick(ClickEvent event) {
							popup.hide();
							popup.clear();
						}
					});
					
					SimplePanel sp = new SimplePanel();
					sp.setSize("5px", "20px");
					
					HorizontalPanel hp = new HorizontalPanel();
					hp.add(yesButton);
					hp.add(new Label("         "));
					hp.add(noButton);
					
					vp.add(sp);
					vp.add(hp);
					popup.add(vp);
					popup.show();
				}
			}
		});
		absolutePanel.add(deleteGroupButton, 54, 604);
		deleteGroupButton.setSize("53px", "24px");
		
		editGroupButton = new Button("Edit");
		editGroupButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				enableForm();
				groupListbox.setEnabled(false);
			}
		});
		absolutePanel.add(editGroupButton, 113, 604);
		editGroupButton.setSize("38px", "24px");
		
		groupListbox = new ListBox();
		groupListbox.addChangeHandler(new ChangeHandler() {
			public void onChange(ChangeEvent event) {
				populateForm();
				if (selectedGroup != null) {
					cancelGroup = new Group(selectedGroup);
				}
			}
		});
		groupListbox.setVisibleItemCount(20);
		absolutePanel.add(groupListbox, 10, 34);
		groupListbox.setSize("259px", "564px");
		
		saveGroupButton = new Button("Save Group");
		saveGroupButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
								
				if (groupNameTextbox.getText().equals("")) {
					Window.alert("A name must be spcified for the event.");
					return;
				}
				if (personListBox.getItemCount() < 1) {
					Window.alert("A volunteer must be added in order to save the Group.");
					return;
				}
				if (descriptionTextArea.getText().equals("")) {
					Window.alert("A description is required in order to save the Group.");
					return;
				}
						
				if (selectedGroup == null) {
					selectedGroup = new Group();
					groupCopy = null;
				}
				else {
					groupCopy = new Group(selectedGroup);
				}
				
				selectedGroup.setName(groupNameTextbox.getText());				
				selectedGroup.setPersonList(new Vector<Person>());
				
				if (personListBox.getItemCount() > 0) {
					for (Person person : addedPersonVector) {
						if (person == null)
							continue;

						selectedGroup.getPersonList().add(person);
					}
				}
				
				selectedGroup.setDescription(descriptionTextArea.getText());
				
				if (privateCheckbox.getValue())
					selectedGroup.setPublic(false);
				else
					selectedGroup.setPublic(true);
				
				databaseHandlerService.write(selectedGroup, new AsyncCallback<Integer>() {

					@Override
					public void onFailure(Throwable caught) {
						Window.alert("Error: unable to save the group. " + relogString + " " + caught.toString());
						if (groupCopy != null) {
							selectedGroup = new Group(groupCopy);
						}
					}

					@Override
					public void onSuccess(Integer result) {
						if (groupCopy == null) {
							groupListbox.addItem(selectedGroup.getName());
							groupVector.add(selectedGroup);
							selectedGroup.setId(result);
							groupListbox.setSelectedIndex(groupVector.size() - 1);
						}
						
						disableForm();
						groupListbox.setEnabled(true);
						
						Window.alert("The group was successfully saved.");
					}
				});
			}
		});
		absolutePanel.add(saveGroupButton, 10, 604);
		saveGroupButton.setSize("97px", "24px");
		
		cancelButton = new Button("Cancel");
		cancelButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if (cancelGroup != null) {
					selectedGroup = new Group(cancelGroup);
				}
				
				if (selectedGroup != null && groupListbox.getSelectedIndex() != -1) {
					populateForm();
					disableForm();
				}
				else {
					clearForm();
					disableForm();
				}
				groupListbox.setEnabled(true);
			}
		});
		absolutePanel.add(cancelButton, 113, 604);
		cancelButton.setSize("97px", "24px");
		
		lblAdditionalPeople = new Label("Volunteers:");
		absolutePanel.add(lblAdditionalPeople, 307, 112);
		lblAdditionalPeople.setSize("79px", "18px");
		
		personListBox = new ListBox();
		personListBox.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if (personListBox.getSelectedIndex() != -1) {
					selectedPerson = addedPersonVector.get(personListBox.getSelectedIndex());
				}
			}
		});
		personListBox.setVisibleItemCount(5);
		personListBox.setEnabled(false);
		absolutePanel.add(personListBox, 307, 136);
		personListBox.setSize("232px", "462px");
		
		addPersonButton = new Button("Add");
		addPersonButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				//TODO: show loading
				appp = new AddPersonPopupPanel(personVector);
				appp.setPopupPosition(groupNameTextbox.getAbsoluteLeft(), groupNameTextbox.getAbsoluteTop());
				appp.setGlassEnabled(true);
				appp.addPersonButton.addClickHandler(new ClickHandler() {
					
					@Override
					public void onClick(ClickEvent event) {
						if (appp.addedPersonVector != null && !appp.addedPersonVector.isEmpty()) {
							for (Person person: appp.addedPersonVector) {
								if (person == null)
									continue;
								
								personListBox.addItem(person.getFirstName() + " " + person.getLastName());
								addedPersonVector.add(person);
							}	
						}
						
						personVector = new Vector<Person>(appp.personVector);
						
						appp.hide();
						appp.clear();
					}
				});
				appp.cancelButton.addClickHandler(new ClickHandler() {
					
					@Override
					public void onClick(ClickEvent event) {
						appp.hide();
						appp.clear();
					}
				});				
				
				appp.show();
			}
		});
		addPersonButton.setEnabled(false);
		absolutePanel.add(addPersonButton, 307, 604);
		addPersonButton.setSize("38px", "24px");
		
		removePersonButton = new Button("Remove");
		removePersonButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if (selectedPerson != null && personListBox.getSelectedIndex() != -1) {					
						personVector.add(selectedPerson);
						addedPersonVector.remove(selectedPerson);
						personListBox.removeItem(personListBox.getSelectedIndex());
						selectedPerson = null;			
				}
			}
		});
		removePersonButton.setEnabled(false);
		absolutePanel.add(removePersonButton, 351, 604);
		removePersonButton.setSize("63px", "24px");
		
		Label lblDescription = new Label("Description:");
		absolutePanel.add(lblDescription, 577, 112);
		
		descriptionTextArea = new TextArea();
		absolutePanel.add(descriptionTextArea, 577, 136);
		descriptionTextArea.setSize("282px", "456px");
		
		privateCheckbox = new CheckBox("This is a private group");
		absolutePanel.add(privateCheckbox, 307, 61);
		
		saveGroupButton.setVisible(false);
		cancelButton.setVisible(false);
		
		disableForm();
	}
		
	// populate form ************************************************************************
	private void populateForm() {
		
		if (groupListbox.getSelectedIndex() != -1) {
			clearForm();
			selectedGroup = groupVector.get(groupListbox.getSelectedIndex());
			
			if (selectedGroup != null) {
				addedPersonVector = new Vector<Person>();
				personVector = new Vector<Person>();
				ContentPanel.getInstance().showLoading(2, 440, 350);
				databaseHandlerService.getAllPeople(new AsyncCallback<Vector<Person>>() {
					
					@Override
					public void onSuccess(Vector<Person> result) {
						//TODO: make removal temporary
						if (result != null && !result.isEmpty()) {
							for (Person person : result) {
								if (person == null)
									continue;
								
								if (person.getUsername().equals("dev"))
									continue;
								
								if (selectedGroup.getPersonList() != null) {
									boolean duplicate = false;
									for ( Person pr : selectedGroup.getPersonList()) {
										if (pr == null)
											continue;
										
										if (person.getUsername().equals("dev"))
											continue;
										
										if (pr.getID() == person.getID()) {
												duplicate = true;
												break;
										}
									}
									
									if (duplicate) {
										addedPersonVector.add(person);
										personListBox.addItem(person.getFirstName() + " " + person.getLastName());
									}
									else {
										personVector.add(person);
									}
								}
								else {
									personVector.add(person);
								}
							}
						}
						
						groupNameTextbox.setText(selectedGroup.getName());
						ContentPanel.getInstance().hideLoadingPopup(2);
					}
					
					@Override
					public void onFailure(Throwable caught) {
						ContentPanel.getInstance().hideLoadingPopup(2);
						Window.alert("Error: Failed to retrieve list of Volunteers. " + relogString);
					}
				});
			}
			descriptionTextArea.setText(selectedGroup.getDescription());
			
			if (selectedGroup.isPublic())
				privateCheckbox.setValue(false);
			else 
				privateCheckbox.setValue(true);
			
			disableForm();
			groupListbox.setEnabled(true);
		}
	}
	
	private void disableForm() {
		groupNameTextbox.setEnabled(false);
		
		personListBox.setEnabled(false);
		addPersonButton.setEnabled(false);
		removePersonButton.setEnabled(false);
		
		addGroupButton.setEnabled(true);
		editGroupButton.setEnabled(true);
		deleteGroupButton.setEnabled(true);
		
		descriptionTextArea.setEnabled(false);
		privateCheckbox.setEnabled(false);
		
		saveGroupButton.setVisible(false);
		cancelButton.setVisible(false);
	}
	
	private void enableForm() {
		groupNameTextbox.setEnabled(true);
		
		personListBox.setEnabled(true);
		addPersonButton.setEnabled(true);
		removePersonButton.setEnabled(true);
				
		addGroupButton.setEnabled(false);
		editGroupButton.setEnabled(false);
		deleteGroupButton.setEnabled(false);
		
		descriptionTextArea.setEnabled(true);
		privateCheckbox.setEnabled(true);
		
		saveGroupButton.setVisible(true);
		cancelButton.setVisible(true);
	}
	
	private void clearForm() {
		groupNameTextbox.setText("");
		personListBox.clear();
		descriptionTextArea.setText("");
		privateCheckbox.setValue(false);
	}
}
